﻿using System;

namespace Cpu6502.Opcodes
{
    /// <summary>
    /// INC $AAAA, Increment memory using absolute address.
    /// </summary>
    class INC_A : Opcode
    {
        public INC_A()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.Absolute;
        }

        public override void Execute()
        {
            Byte temp  = CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.Absolute)
                ];

            temp = (byte)((temp + 1) & 0xff);
            
            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.Absolute)
                ] = temp;
        }
    }

    /// <summary>
    /// INC $AAAA, X, Increment memory using absolute address X.
    /// </summary>
    class INC_A_X : Opcode
    {
        public INC_A_X()
        {
            this.CpuCycles = 7;
            this.AddressType = CPU.AddressType.AbsoluteIndexedX;
        }

        public override void Execute()
        {
            Byte temp = CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.AbsoluteIndexedX)
                ];

            temp = (byte)((temp + 1) & 0xff);

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.AbsoluteIndexedX)
                ] = temp;
        }
    }

    /// <summary>
    /// INC $AA, Increment memory using ZeroPage.
    /// </summary>
    class INC_ZP : Opcode
    {
        public INC_ZP()
        {
            this.CpuCycles = 5;
            this.AddressType = CPU.AddressType.ZeroPage;
        }

        public override void Execute()
        {
            Byte temp = CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPage)
                ];

            temp = (byte)((temp + 1) & 0xff);

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPage)
                ] = temp;
        }
    }

    /// <summary>
    /// INC $AA, X - Increment memory using ZeroPage X.
    /// </summary>
    class INC_ZP_X : Opcode
    {
        public INC_ZP_X()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.ZeroPageIndexedX;
        }

        public override void Execute()
        {
            Byte temp = CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPageIndexedX)
                ];

            temp = (byte)((temp + 1) & 0xff);

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPageIndexedX)
                ] = temp;
        }
    }
}
